function loadSVG(loc, success, failure) {
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4) {
			if (xmlhttp.status == 200) {
				success.call(this, new SVG(xmlhttp.responseXML));
			}
			else {
				fail.call(this, loc);
			}
 
 		}	
	}
	xmlhttp.open("GET", loc, true);
	xmlhttp.send(null);
}

var SVG = function(node) {
	
	this.paths = [];
	
	node = node.getElementsByTagName("svg").item(0);
	
	for (var i = 0; i < node.childNodes.length; i++) {
		this.paths.push(new Path(node.childNodes.item(i)));
	}
	
	// Draws every path in this SVG to the specified context.
	this.draw = function(context) {

		for (var i = 0; i < this.paths.length; i++) {
			this.paths[i].draw(context);
		}
	};
	
}

var Path = function(something) {

	this.commands = commands(something);
	
	this.lineWidth = 1;
    this.strokeStyle = "#000000";
    this.fillStyle = "#FFFFFF";
	
	var turtle = function() {
		this.x;
		this.y;
		this.x2;
		this.y2;
		this.reset = function() {
			this.x = this.y = this.x2 = this.y2 = 0;
		}
		this.reset();
	}
		
	// Draws this entire path to the specified context.
	this.draw = function(context) {
		this.style(context);
		context.beginPath();
		this.shape(context);

		this.end(context);
		
	};

	// Calls canvas shape methods such as moveTo(), lineTo(), bezierCurveTo() based on the commands in this path.
	this.shape = function(context) {
		for (var i = 0; i < this.commands.length; i++) {
			this.commands[i].shape(context, turtle);
		}
	};
	
	// Sets the drawing style of the canvas context based on the styles in this Path.
	this.style = function(context) {
		// TODO
	};
	
	// Calls context.fill() and/or context.stroke() depending on the styles in this Path.
	this.end = function(context) {
		context.fill();
	}

}

var Command = function(type, data) {
	this.type = type;
	this.data = data;
	
	// Calls context shape methods such as moveTo(), lineTo(), bezierCurveTo(), etc.
	this.shape = function(c, turtle) {
		
		if (this.type == "M") {
		
			turtle.x = this.data[0];
			turtle.y = this.data[1];
			c.moveTo(turtle.x, turtle.y);
		
		} else if (this.type == "C") {
		
			turtle.x = this.data[4];
			turtle.y = this.data[5];
			c.bezierCurveTo(this.data[0],
							this.data[1], 
							turtle.x2 = this.data[2], 
							turtle.y2 = this.data[3], 
							turtle.x, 
							turtle.y);
		
		} else if (this.type == "c") {
		
			c.bezierCurveTo(turtle.x+this.data[0], 
							turtle.y+this.data[1], 
							turtle.x2 = turtle.x+this.data[2], 
							turtle.y2 = turtle.y+this.data[3], 
							turtle.x += this.data[4], 
							turtle.y += this.data[5]);
		
		} else if (this.type == "S") {
			
			turtle.x = this.data[2];
			turtle.y = this.data[3];
			var dx = turtle.x - turtle.x2;
			var dy = turtle.y - turtle.y2;
			c.bezierCurveTo(turtle.x+dx, 
							turtle.y+dy, 
							turtle.x2 = this.data[0], 
							turtle.y2 = this.data[1], 
							turtle.x, 
							turtle.y);
		
		} else if (this.type == "s") {
		
			var dx = turtle.x - turtle.x2;
			var dy = turtle.y - turtle.y2;
			c.bezierCurveTo(turtle.x+dx, 
							turtle.y+dy, 
							turtle.x2 = turtle.x+this.data[0], 
							turtle.y2 = turtle.y+this.data[1], 
							turtle.x += this.data[2], 
							turtle.y += this.data[3]);
		
		} else if (this.type == "L") {
		
			c.lineTo(turtle.x, 
					 turtle.y, 
					 turtle.x = this.data[0], 
					 turtle.y = this.data[1]);
		
		} else if (this.type == "l") {
	
			c.lineTo(turtle.x, turtle.y, turtle.x+=this.data[0], turtle.y+=this.data[1]);
			
		} else if (this.type == "H") {
	
			c.lineTo(turtle.x = this.data[0], turtle.y)
			
		} else if (this.type == "h") {
		
			c.lineTo(turtle.x += this.data[0], turtle.y)     
			
		} else if (this.type == "V") {
		
			c.lineTo(turtle.x, turtle.y=this.data[0]);
		
		} else if (this.type == "v") {
		
			c.lineTo(turtle.x, turtle.y+=this.data[0]); 
		
		} else {
		
			alert("unrecognized command " + this.type);
			
		}
	
	}
	
}

// Utility functions


var commands = function(element) {
	
	if (element.nodeName == "path") {
		return commandsFromD(element.getAttribute("d"));
	}
		
	if (element.nodeName == "polygon") {
		return commandsFromPoints(element.getAttribute("points"));
	}
	
	return [];
	
}

// Returns an array of commands as interpreted by the "d" attribute of a path.
var commandsFromD = function(d) {
	
	var toReturn = [];
	var commands = d.match(/[a-zA-Z][0-9\.\-\,]+/g);
	
	for (var i = 0; i < commands.length; i++) {
	
	var type = commands[i].charAt(0);
	
	// Dirty time.
	var commandData = commands[i].substr(1);
	commandData = commandData.replace(/\-/g, ",-")
	
	if (commandData.charAt(0) == ",") {
	 commandData = commandData.substr(1);
	}
	commandData = commandData.split(",");
	for (var j = 0; j < commandData.length; j++) {
	commandData[j] = parseFloat(commandData[j]);
	}
	
	toReturn.push(new Command(type, commandData));
	
	}
	
	return toReturn;
}

// Returns an array of commands as interpreted by the "points" attribute of a polygon.
var commandsFromPoints = function(pointAttribute) {
	pointAttribute = pointAttribute.replace(/\,\-/g, "-");
	pointAttribute = "M"+pointAttribute;
	pointAttribute = pointAttribute.replace(/ /g, "L");
	return commandsFromD(pointAttribute);
}